perm filename SERVO.FAI[CMS,LCS]2 blob
sn#409368 filedate 1979-01-04 generic text, type T, neo UTF8
00100 TITLE SERVO
00200 .INSERT ASMBL.FAI[CMS,LCS]
00300
00400 ;I/O address definitions.
00500 DAC ← 100000 ;8 bit DAC.
00600 JCR ← 120000 ;Joint control output register.
00700 ENCL ← 140000 ;Encoder mux low.
00800 ENCH ← 140001 ;Encoder mux high.
00900
01000 STKSIZ ← 377 ;Stack size.
01100 OFF ← 377 ;?
01150 LSBENB ← 40 ;Enable LSB servo.
01175 DBLMOD ← 20 ;Double all position commands for
01187 ;joints that have extremely low gearing.
01200
01300 ;Zero page variables.
01400 ;Not shared?
01500
01550 IOCTRL: 0 ;Copy of JCR output port.
01600 CURVEL: BLOCK 2 ;Current velocity.
01700 0
01800 SETPT: BLOCK 3 ;Current setpoint.
01900 0
02000 SETINC: BLOCK 3 ;Interpolating increment for setpoints.
02100 PREDCT: BLOCK 3 ;Result of the predictive term.
02200 LSTINX: BLOCK 3 ;Position at last index pulse.
02300 OLDSP: BLOCK 3 ;Last commanded setpoint, for CMDVEL.
02400 POSERR: BLOCK 3 ;Current position error.
02500 DACSIG: BLOCK 3 ;Scratch.
02600
03700 BGLOCK: 0 ;Interlock around background pre. cal.
03800 DSPAT: BLOCK 2 ;Dispatch address when cmds are rcvd?
03900 DSPAT2: BLOCK 2 ;Dispatch when commands are executed?
04000 INCTR: 0 ;Count the interpolations.
04100 HSTTMR: 0 ;Count ticks between host commands.
04200
04300 LOGTMP: BLOCK 4 ;Temp for the arithmetic routines.
04400 CVSAV: BLOCK 2 ;Save area for background variables.
04500 VELSAV: BLOCK 2
04600 BGTMP: BLOCK 2
04700
04800 ZAPEND ← .-1 ;Clear all the above in startup.
04900
05000 CURPOS: BLOCK 3 ;Current position, extended to 3 bytes.
05050
05100 TL: 0 ;Scratch for grey to binary.
05200 TH: 0
00100 ;Shared ram. Check all refs.
00200 LOC 200 ;Second half of zero page.
00300
00400 STATUS: 0 ;Flags for the host.
00500 MODE: 0 ;Mode bits from host.
00550
00575 CKWORD: BLOCK 2 ;Host I/O check/command word.
00587 CMDPOS: BLOCK 2 ;Commanded position from host.
00600
00620 BUSLO: 0 ;Buffer?
00640 BUSHI: 0 ;?
00660
00700 MEMPTR: BLOCK 2 ;Address pointer for diagnostic read.
00720 ;NINTER = function of INTSCL?
00800 NINTER: 0 ;# of interpolations between position
00900 ;commands.
01000 INTSCL: 0 ;# of bits to shift setpoint dif for
01100 ;interpolating.
01200 HSTLIM: 0 ;# of clock ticks allowed between host
01300 0 ;commands.
01400 CMDVEL: BLOCK 2 ;Commanded velocity.
01500 MASS: BLOCK 2 ;Inertia term for prediction.
01600 FRICTN: BLOCK 2 ;Viscous damping coefficient.
01700 GRAVTY: BLOCK 4 ;DC offset for gravity.
01800 POSTOL: BLOCK 4 ;Half-width of position tolerance band.
01900 INTTOL: BLOCK 4 ;Half-width of integration band.
00100 ;Add SEI and CLI to all shared ram refs.
00150 ;Add ? for IOCTRL read?
00200 START: CLD
00300 LDXI STKSIZ ;Setup stack.
00400 TXS
00500
00520 ;Zero shared ram?
00600 LDAI 0
00700 LDXI ZAPEND
00800 RLOOP: STAZX 0 ;Reset ram.
00900 DEX
01000 BPL RLOOP
01100 STAZ CURPOS+2;?
01200
01300 TAY
01400 BEQ RSTDEF ;Jump
01500
01600
01700 DLOOP: INY
01800 LDAY INITBL ;Init ram.
01900 STAZX 0
02000 INY
02100
02200 RSTDEF: LDXZY INITBL
02300 CPXI 377
02400 BNE DLOOP
02500
02600 JSR POSUPD ;?
02700 JSR SETPOS ;?
02800
02900 CLI ;?
03000
03100 RSTCKW: LDAI 0 ;Reset check word.
03120 SEI
03200 STAZ CKWORD
03300 STAZ CKWORD+1
03400 CLI
03450 ;Idle loop. Wait for command.
03500 IDLE: LDXZ CKWORD+1;+1 for no lock.
03600 BEQ IDLE
03700
03800 SEI
03900 LDAZ CKWORD ;Get check word.
04000 LDXZ CKWORD+1
04100 CLI
04200
04210 ;CKWORD is command?
04220 SEI
04230 LDAZ CMDPOS ;Get position.
04240 LDXZ CMDPOS+1
04250 CLI
04260 ;Position command.
04300
04400 INITBL: STATUS ↔ 200
04500 NINTER ↔ =32
04600 INTSCL ↔ 5
04700 HSTLIM ↔ =48
04800 DSPAT+1 ↔ (IMBLK⊗-10)∧377
04900 DSPAT2+1 ↔ (DFBLK⊗-10)∧377
05000 DAC ↔ 0
05100 377
00100 ;Clock tick interrupt.
00200 TICK: PHA ;Save state.
00300 TXA
00400 PHA
00500 TYA
00600 PHA
00700
00800 LDY ENCL ;Read encoder.
00900 LDA ENCH
01000
01100 ;Convert from grey to binary.
01200 STAZ TH
01300 LSRA
01400 EORZ TH
01500 STAZ TH
01600 TAX
01700
01800 TYA
01900 STAZ TL
02000 RORA
02100 EORZ TL
02200 STAZ TL
02300
02400 LSRZ TH
02500 RORA
02600 LSRZ TH
02700 RORA
02800
02900 EORZ TL
03000 STAZ TL
03100 TAY
03200 TXA
03300 EORZ TH
03400 STAZ TH
03500
03600 LSRA
03700 RORZ TL
03800 LSRA
03900 RORZ TL
04000 LSRA
04100 RORZ TL
04200 LSRA
04300 RORZ TL
04400
04500 EORZ TH
04600 STAZ TH
04700 TYA
04800 EORZ TL
04900 EORZ TH
05000 STAZ TL ;?
05100 TAY ;?
05200 ;Extend sign from n bits?
05300 ; LDXZ TH ?
00100 JSR POSUPD ;Put POSUPD here?
00200
00300 STAZ CURPOS
00400 STXZ CURPOS+1
00500 STYZ CURPOS+2
00600
00700 DECZ HSTTMR
00800 BPL HOSTOK
00900
01000 LDAI 0
01100 STAZ HSTTMR
01200 STAZ CMDVEL
01300 STAZ CMDVEL+1
01400
01450 ;IOCTRL is copy of JCR?
01500 HOSTOK: LDAI 4
01600 BITZ IOCTRL ;?If position mode is off,
01700 BNE INTRS
01800 JMP CURSRV ;don't servo.
01900
02000 ;Interpolate the setpoints.
02100 INTRS: CLC
02200 LDAZ SETPT-1
02300 ADCZ SETINC-1
02400 STAZ SETPT-1
02500 LDAZ SETPT
02600 ADCZ SETINC
02700 STAZ SETPT
02800 LDAZ SETPT+1
02900 ADCZ SETINC+1
03000 STAZ SETPT+1
03100 LDAZ SETPT+2
03200 ADCZ SETINC+2
03300 STAZ SETPT+2
03400
03500 DECZ INCTR
03600 BNE GPOSER
03700
03800 LDAI 0
03900 STAZ SETINC-1
04000 STAZ SETINC
04100 STAZ SETINC+1
04200 STAZ SETINC+2
04300
04400 ;Calculate the position error.
04500 GPOSER: SEC
04600 LDAZ CURPOS
04700 SBCZ SETPT
04800 STAZ POSERR
04900 LDAZ CURPOS+1
05000 SBCZ SETPT+1
05100 STAZ POSERR+1
05200 LDAZ CURPOS+2
05300 SBCZ SETPT+2
05400 STAZ POSERR+2
00100 BITZ MODE ;?If servo is disabled, we're
00200 BPL OOTOL ;automatically out of tolerance
00300
00400 LDAZ POSERR+2;Test the sign of pos error.
00500 BMI NEGPER
00600
00700 LDAZ POSTOL ;Positive. Compare with tol.
00800 CMPZ POSERR
00900 LDAZ POSTOL+1
01000 SBCZ POSERR+1
01100 LDAI 0
01200 SBCZ POSERR+2
01300 BCS TOLOK ;In tolerance.
01400 BCC OOTOL ;Jump.
01500
01600 NEGPER: CLC ;Negative. Add the tolerance.
01700 LDAZ POSTOL
01800 ADCZ POSERR
01900 LDAZ POSTOL+1
02000 ADCZ POSERR+1
02100 LDAI 0
02200 ADCZ POSERR+2
02300 BCS TOLOK ;In tolerance.
02400
02500 OOTOL: LDAZ IOCTRL ;Out of tolerance.
02600 ANDI 177 ;Turn off the in tolerance
02700 BNE WCNTRL ;indicator.
02800
02900 TOLOK: LDAZ IOCTRL ;In tolerance. Turn it on.
03000 ORAI 200
03100 WCNTRL: STAZ IOCTRL
03150 STA JCR ;Copy it to output.
03200
03300 BITZ MODE ;If intergration is disabled,
03400 BVC OOBAND ;turn it off.
03500 LDAZ POSERR+2;Test sign of position error.
03600 BMI ADTOL
03700
03800 LDAZ INTTOL ;Positive. Compare with tol.
03900 CMPZ POSERR
04000 LDAZ INTTOL+1
04100 SBCZ POSERR+1
04200 LDAI 0
04300 SBCZ POSERR+2
04400 BCS INBAND
04500 BCC OOBAND
04600
04700 ADTOL: CLC ;Negative. Add the tolerance.
04800 LDAZ INTTOL
04900 ADCZ POSERR
05000 LDAZ INTTOL+1
05100 ADCZ POSERR+1
05200 LDAI 0
05300 ADCZ POSERR+2
05400 BCS INBAND
05500
05600 OOBAND: LDAZ IOCTRL ;Out of band. Turn off
05700 ORAI 10 ;integration by setting the
05800 ANDI 357 ;control bit. LSB servo off.
05900 BNE WCTRL2
00100 INBAND: LDAI LSBENB ;In band. Is LSB servo enabled
00200 BITZ MODE
00300 BEQ RCNTRL
00400
00500 LDAZ POSERR ;Yes. Is the error exactly 0?
00600 ORAZ POSERR+1
00700 ORAZ POSERR+2
00800 BNE RCNTRL
00900
01000 LDAZ IOCTRL ;It is. Integration off, LSB
01100 ORAI 30 ;servo on.
01200 BNE WCTRL2 ;Jump.
01300
01400 RCNTRL: LDAZ IOCTRL ;LSB disabled or error
01500 ANDI 347 ;not zero. LSB servo off,
01600 ;integration on.
01700
01800 WCTRL2: STAZ IOCTRL
01900 STA JCR ;Output it.
00100 LDAZ LOGTMP ;Since the arithmetic routines
00200 LDYZ LOGTMP+1;aren't re-entrant, we need to
00300 STAZ LOGTMP+2;save their state here.
00400 STYZ LOGTMP+3
00500
00600 LDYZ CURVEL ;Get the velocity,
00700 LDAZ CURVEL+1
00800 JSR LOG
00900 LDXI FRICTN ;mult. by the friction
01000 JSR MULTIP ;coefficient,
01100 JSR EXP
01200 TAX
01300 TYA
01400 CLC ;add the position error...
01500 ADCZ POSERR
01600 STAZ DACSIG
01700 TXA
01800 ADCZ POSERR+1
01900 STAZ DACSIG+1
02000 LDYI 0
02100 TXA ;(sign-extend the velocity)
02200 BPL NODEY
02300 DEY
02400
02500 NODEY: TYA
02600 ADCZ POSERR+2
02700 STAZ DACSIG+2
02800
02900 CLC ;...the velocity predictive term...
03000 LDAZ DACSIG
03100 ADCZ PREDCT
03200 STAZ DACSIG
03300 LDAZ DACSIG+1
03400 ADCZ PREDCT+1
03500 STAZ DACSIG+1
03600 LDAZ DACSIG+2
03700 ADCZ PREDCT+2
03800 STAZ DACSIG+2
03900
04000 CLC ;...and the gracity offset.
04100 LDAZ DACSIG
04200 ADCZ GRAVTY
04300 TAY
04400 LDAZ DACSIG+1
04500 ADCZ GRAVTY+1
04600 TAX
04700 LDAZ DACSIG+2
04800 ADCZ GRAVTY+2
04900
04950 ;Put PUTDAC here?
05000 JSR PUTDAC ;Put result out to the DAC.
05100
05200 LDYZ LOGTMP+3;Restore the arithmetic
05300 LDAZ LOGTMP+2;routines' state.
05400 STYZ LOGTMP+1
05500 STAZ LOGTMP
05600 CMDSP: ;Add deferred commands here?
00050 ;Change CMDEND for no host command interrupt?
00100 CMDEND: LDAI 4 ;Done with commands.
00200 BITZ IOCTRL ;Are we servoing?
00300 BEQ INTXIT
00400 BITZ BGLOCK ;Yes. Is the background
00500 BMI INTXIT ;predictor still running?
00600
00700 DECZ BGLOCK ;No. Start it up.
00800 JMP BGSRV
00900
01000 BGDON: INCZ BGLOCK ;Unlock?
01100
01200 INTXIT: PLA ;Restore state and dismiss interrupt.
01300 TAY
01400 PLA
01500 TAX
01600 PLA
01700 RTI
01800
01850 ;Stop mode?
01900 CURSRV: ;Not servoing ("Current mode")...
02000 JMP CMDSP
02100
02200 ;Background velocity prediction.
02300 BGSRV: LDAZ CURVEL ;Copy the variables used to
02400 STAZ VELSAV ;avoid interference from
02500 LDAZ CURVEL+1;interrupts while this routine
02600 STAZ VELSAV+1;is running.
02700 LDAZ CMDVEL
02800 STAZ CVSAV
02900 LDAZ CMDVEL+1
03000 STAZ CVSAV+1
03100 LDYZ POSERR
03200 LDAZ POSERR+1
03300 LDXZ POSERR+2
03400
03500 CLI ;Enable interrupts?
03600
03700 PHA
03800 ASLA ;Is magnitude of position error
03900 TXA ;< 2↑15?
04000 ADCI 0
04100 BEQ FLOERR
04200
04300 PLA ;No. Set the predictive term to zero.
04400 LDAI 0
04500 TAX
04600 TAY
04700 JMP NTRLOC
04800
04900 FLOERR: PLA ;Yes. Float the position error.
05000 JSR LOG
05100 JSR INV ;TMP = 1 / POSERR
05200 STYZ BGTMP
05300 STAZ BGTMP+1
05400 CLC
05500 LDAZ CVSAV ;Commanded velocity + current
05600 ADCZ VELSAV ;velocity...
05700 TAY
05800 LDAZ CVSAV+1
05900 ADCZ VELSAV+1
00100 JSR LOG ;...float...
00200 LDXI BGTMP
00300 JSR MULTIP ;...* TMP...
00400 STYZ BGTMP ;...stored at TMP.
00500 STAZ BGTMP+1
00600 SEC
00700 LDAZ CVSAV ;Commanded velocity - current
00800 SBCZ VELSAV ;velocity...
00900 TAY
01000 LDAZ CVSAV+1
01100 SBCZ VELSAV+1
01200 JSR LOG ;...same thing.
01300 LDXI BGTMP
01400 JSR MULTIP
01500 STYZ BGTMP
01600 STAZ BGTMP+1
01700
01800 SEI ;Interlock...
01900
02000 LDYZ MASS ;...get the mass...
02100 LDAZ MASS+1
02200
02300 CLI ;clear the lock.
02400
02500 JSR MULTIP ;Scale the predictor.
02600 JSR EXP ;Back to integer form.
02700 LDXI 0
02800 CMPI 0
02900 BPL NTRLOC ;Extend sign to 3 bytes.
03000 DEX
03100
03200 NTRLOC: SEI ;End of background. Interlock.
03300
03400 STYZ PREDCT
03500 STAZ PREDCT+1;Store the result for the servo
03600 STXZ PREDCT+2;to use.
03700 JMP BGDON
00100 INTBL: ;IMMEDIATE COMMAND TABLE?
00200 HCIRDM∧377 ;Read memory.
00300
00400 HCISRV∧377 ;Position mode?
00500
00600 CMTBL: ;DEFERRED COMMAND TABLE?
00900 CMDEND∧377 ;Read memory?
01000
01100 CMDSRV∧377 ;Position mode?
00100 ;Subroutines?
00200 ;Enter with position in A (low), X (middle), Y (high).
00300 ;Sets current position to that value, puts the setpoint
00400 ;to the same, clears the setpoint interpolating
00500 ;increment, and goes into stop mode.
00600 ;??
01400 SETPOS: STAZ CURPOS ;Set the current position.
01500 STXZ CURPOS+1
01600 STYZ CURPOS+2
01700
01800 ;Second entry - freeze to the position in A, X, Y as
01900 ;above without changing the current position.
02000 ;??
02100 FREZE: STAZ SETPT ;Set the position command.
02200 STXZ SETPT+1
02300 STYZ SETPT+2
02400 STAZ OLDSP
02500 STXZ OLDSP+1
02600 STYZ OLDSP+2
02700
02800 LDAI 75 ;I/O control bits for servo
02900 STAZ IOCTRL ;enable on, all others off.
02950 STA JCR
03000
03100 LDAI 0
03200 STAZ SETPT-1 ;Clear the setpoint extension
03300 STAZ SETINC-1;and the interpolator
03400 STAZ SETINC
03500 STAZ SETINC+1
03600 STAZ SETINC+2
03700 STAZ CMDVEL ;and the commanded velocity.
03800 STAZ CMDVEL+1
03900
04000 LDAZ SETPT ;Return the regs. unchanged.
04100 RTS
04200
04300 ;Enter with low counter value in Y.
04400 ;Returns updated position in A (low), X (middle),
04500 ;Y (high). Also sets CURVEL to the 16-bit signed
04600 ;velocity.
04700 ;??
04800 POSUPD: STAZ DACSIG+1;Save high byte.
04820 TYA
05100 STAZ DACSIG ;Save that value.
05300 SEC
05400 SBCZ CURPOS ;Subtract the old position
05500 STAZ CURVEL ;yielding the velocity.
05520 LDAZ DACSIG+1
05540 SBCZ CURPOS+1
05560 STAZ CURVEL+1
05900 LDXZ CURPOS+1 ;Set up for updating bytes
06000 LDYZ CURPOS+2 ;2 and 3.
06100 LDAZ DACSIG+1;Did bit 15 of pos. change?
06200 EORZ CURPOS+1
06300 BPL GETDAC ;If not, we're through.
06400 LDAZ CURVEL+1;It did. Which way did we move
06500 BMI DOWN
06600 LDAZ DACSIG+1;Upward.
06700 BMI GETDAC ;If bit 15 is on, we're done.
07000 INY ;Off. Increment high byte.
07100 JMP GETDAC
07200
07300 DOWN: LDAZ DACSIG+1;Downward.
07400 BPL GETDAC ;If bit 15 is off, we're done.
07500 DEY ;Decrement high byte.
07900
08000 GETDAC: LDAZ DACSIG
08100 RTS
00100 ;DAC output subroutine. Not sub?
00200 ;Enter with 3 byte value in Y (low), X (middle),
00300 ;A (high). Clobbers all registers, but the 8 bits the
00400 ;DAC got are returned in?
00500 PUTDAC: BMI NEGDAC ;Assuming the last I. loaded A.
00600 CPYI 200 ;Positive. Compare with 2↑7.
00700 BCS TOOHI
00800 CPXI 1
00900 SBCI 0
01000 BCC INRNGE
01100
01200 TOOHI: LDYI 177 ;Too high. Saturate positive.
01300 BNE INRNGE ;Jump.
01400
01500 NEGDAC: CPYI 200 ;Negative. Compare with -2↑7.
01600 BCC TOOLOW
01700
01800 CPXI 377
01900 SBCI 377
02000 BCS INRNGE
02100
02200 TOOLOW: LDYI 200 ;Too low. Saturate to -2↑7.
02300
02400 INRNGE: STY DAC ;Output 8 bits to the DAC.
02500 RTS
02600
02700 DOUBLE: PHA ;Doubles the position in (Y,X,A) if
02800 LDAI DBLMOD ;the double mode bit is set.
02900 BITZ MODE
03000 BEQ NOTDBL
03100 PLA
03200 ASLA
03300 PHA
03400 TXA
03500 ROLA
03600 TAX
03700 TYA
03800 ROLA
03900 TAY
04000 NOTDBL: PLA
04100 RTS
04200
04300 HALVE: PHA ;Halve the position argument in (Y,X,A)
04400 LDAI DBLMOD ;if the double mode bit is set.
04500 BITZ MODE
04600 BEQ NOTDBL
04700 TYA
04800 CMPI 200
04900 RORA
05000 TAY
05100 TXA
05200 RORA
05300 TAX
05400 PLA
05500 RORA
05600 RTS
00100 ;No index?
00200 ENBTST: PHA ;Test for servo enabled.
00300 LDAZ MODE
00400 ANDI 202
00500 CMPI 200
00600 BNE NOTENB
00700 PLA ;OK. Return.
00720 RTS
00800
00900 NOTENB: PLA ;No. Wipe the return address and
01000 PLA ;end this command.
01100 PLA
01200 JMP CMDEND
00100 ;Arithmetic routines.
00200 ;Enter with high byte in A, low in Y.
00300 ;Returns A = characteristic and sign, Y = mantissa.
00400 ;Clobbers X, LOGTMP, LOGTMP+1.
00500 LOG: STYZ LOGTMP ;Save the inputs.
00600 STAZ LOGTMP+1
00700
00800 LDXI 20+100 ;?Init characteristic to 15.
00900 CMPI 0 ;Test sign of input.
01000 BPL POSIN
01100 SEC ;Negative. 2's complement it.
01200 LDAI 0
01300 SBCZ LOGTMP
01400 STAZ LOGTMP
01500 LDAI 0
01600 SBCZ LOGTMP+1
01700 POSIN: BNE NORML ;Is high byte zero?
01800 LDAZ LOGTMP ;Yes. Low byte?
01900 BEQ RTRN ;If so, return zero.
02000 LDYI 0 ;Low nonzero. Shift left one
02100 STYZ LOGTMP ;byte,
02200 LDXI 10+100 ;?change characteristic to 7.
02300 NORML: DEX ;Normalize the number, counting the
02400 ASLZ LOGTMP ;characteristic down. When the
02500 ROLA ;first "1" shifts out, we've subtracted
02600 BCC NORML ;1 from the normalized number
02700 ASLZ LOGTMP ;(This rounds the result)
02800 ADCI =11 ;and are left with the fraction
02900 TAY ;Adding 11 to that is equivalent to
03000 TXA ;adding 0.043.
03100 ADCI 0 ;Propagate the carry into the
03200 ;characteristic.
03300 ASLA ;Insert the sign bit from the saved
03400 ASLZ LOGTMP+1;input.
03500 RORA
03600 RTRN: RTS ;Done.
03700
03800 ;Enter with sign and characteristic in A, mantissa in Y
03900 ;Returns 16-bit integer, low byte in Y, high in A.
04000 ;Clobbers X, LOGTMP, LOGTMP+1.
04100 EXP: STAZ LOGTMP+1;Save sign of input.
04200 ANDI 177 ;Mask it off.
04300 BEQ ZEROIN ;Zero characteristic returns
04400 TAX ;zero.
04500 TYA ;Get the mantissa...
04600 SEC
04700 SBCI =11 ;...subtract 0.043...
04800 STAZ LOGTMP ;(save this value)
04900 TXA ;...propagate the carry and get rid
05000 SBCI 100 ;of the XS-64 offset.
05100 BMI NEGIN ;If negative (value < 1.0)
05200 ;return zero.
05300 CMPI =15 ;Test for overflow (value>=2↑15
05400 BCS SATUR
05500 TAX ;...no. Number is in range.
05600 ADCI -10 ;?Is characteristic below 8?
05700 BMI BLOATE
05800 TAX ;No. Reduce if by 8,
05900 JSR UNNORM ;unnormalize.
06000 BMI GETTMP ;Jump.
00100 BLOATE: JSR UNNORM ;Yes. Unnormalize, then
00200 ASLZ LOGTMP ;(round result)
00300 ADCI 0
00400 STAZ LOGTMP ;use result as low byte and
00500 LDAI 0 ;set high byte to zero.
00600
00700 GETTMP: LDYZ LOGTMP
00800 GTMP1: LDXZ LOGTMP+1;Test sign of input...
00900 BPL POSIGN
01000 STAZ LOGTMP+1;...negative. 2's complement
01100 LDAI 0 ;the result.
01200 SEC
01300 SBCZ LOGTMP
01400 TAY
01500 LDAI 0
01600 SBCZ LOGTMP+1
01700 POSIGN: RTS
01800
01900 NEGIN: LDAI 0 ;Set the result to zero if the
02000 ZEROIN: TAY ;input is negative.
02100 RTS
02200
02300 SATUR: LDYI OFF ;Saturate result to 2↑15 - 1 if
02400 STYZ LOGTMP ;input was 15 or more.
02500 LDAI 177
02600 BNE GTMP1 ;Jump.
02700
02800 UNNORM: LDAI 1 ;Unnormalize subroutine. Add 1
02900 BNE DECRX ;to the fraction.
03000
03100 SCALE: ASLZ LOGTMP ;Scale the fraction left by the
03200 ROLA ;amount of the characteristic.
03300 DECRX: DEX
03400 BPL SCALE
03500 RTS
03600
03700 ;Enter with characteristic of multiplier in A,
03800 ;mantissa in Y, X pointing to a pair of base page
03900 ;locations containing the multiplicand (mantissa in the
04000 ;low byte).
04100 ;Returns the product in A and Y, same form as the
04200 ;multiplier. Leaves X unchanged. Clobbers LOGTMP and
04300 ;LOGTMP+1.
04400 MULTIP: PHA
04500 EORZX 1 ;Compute sign of result,
04600 STAZ LOGTMP+1 ;save it away.
04700 PLA
04800 ANDI 177 ;Mask off multiplier sign.
04900 BEQ ZEROIN ;If zero, return zero.
05000 STAZ LOGTMP
05100 TYA ;Add the two logarithms.
05200 CLC
05300 ADCZX 0
05400 TAY
05500 LDAZX 1
05600 ANDI 177 ;If multiplicand is zero,
05700 BEQ ZEROIN ;return a zero.
05800 ADCZ LOGTMP
05900 SEC
06000 SBCI 100 ;Correct the XS-64 offset.
00100 BPL INSIGN ;Result in range?
00200 ANDI 100 ;No. If underflow,
00300 BNE NEGIN ;return zero.
00400 LDAI 177 ;Overflow. Saturate to
00500 LDYI 377 ;highest magnitude.
00600
00700 INSIGN: ASLA ;Insert the sign of the result.
00800 ASLZ LOGTMP+1
00900 RORA
01000 RTS
01100
01200 ;Inverse function: 2's complement the magnitude part
01300 ;of a 15-bit logarithm.
01400 ;Enter with characteristic in A, mantissa in Y.
01500 ;Returns inverse in the same form. X unchanged.
01600 ;Clobbers LOGTMP and LOGTMP+1.
01700 INV: STYZ LOGTMP ;Pretty straightforward...
01800 STAZ LOGTMP+1
01900 SEC
02000 LDAI 0 ;Complement the number by
02100 SBCZ LOGTMP ;subtracting it from zero.
02200 TAY
02300 LDAI 0
02400 SBCZ LOGTMP+1
02500 JMP INSIGN ;Insert the original sign.
00100 ;DEFERRED COMMANDS.
00200 ;Fix GRAVTY+2, POSTOL+2, and INTTOL+2.
00300 ;Add DOUBLE to POSTOL and INTTOL.
00400
00420 LOC (.∨377)+1 ;For start of next page.
00500 DFBLK ← .
00600 ;Set parameter command?
00700 CMDSET: STAZX 0 ;?
00800 JMP CMDEND
05200
05300 ;CMDCUR: Stop mode?
00100 CMDSRV: JSR ENBTST
00200 JSR DOUBLE
00300 STAZ DACSIG
00400 STXZ DACSIG+1
00500 STYZ DACSIG+2
00600
00700 SEC
00800 SBCZ SETPT
00900 STAZ SETINC
01000 TXA
01100 SBCZ SETPT+1
01200 STAZ SETINC+1
01300 TYA
01400 SBCZ SETPT+2
01500 LDXI 0
01600 STXZ SETPT-1
01700 STXZ SETINC-1
01800 LDXZ INTSCL
01900
02000 SCAL: CMPI 200 ;Extend sign.
02100 RORA
02200 RORZ SETINC+1
02300 RORZ SETINC
02400 RORZ SETINC-1
02500 DEX
02600 BNE SCAL
02700
02800 STAZ SETINC+2
02900 LDAZ NINTER
03000 STAZ INCTR
03100 SEC
03200 LDAZ DACSIG
03300 SBCZ OLDSP
03400 STAZ CMDVEL
03500 LDAZ DACSIG+1
03600 SBCZ OLDSP+1
03700 STAZ CMDVEL+1
03800 LDAZ DACSIG
03900 STAZ OLDSP
04000 LDAZ DACSIG+1
04100 STAZ OLDSP+1
04200 LDAZ DACSIG+2
04300 STAZ OLDSP+2
04400
04500 LDAZ IOCTRL
04600 ORAI 44
04700 STAZ IOCTRL
04750 STA JCR ;Output it.
04800
04900 LDAZ HSTLIM ;Reset host timer.
05000 STAZ HSTTMR
05100 JMP CMDEND
00100 ;Immediate commands.
00200
00250 LOC (.∨377)+1 ;For start of next page.
00300 IMBLK ← .
00400 HCISRV: ;?
00500
02100 ;Sync, ack?
02200 HCIRDM: LDYZ MEMPTR
02300 LDAY 0
02400 LDXY 1
02500 INY
02600 INY
02700 STYZ MEMPTR
02800
02900 STAZ BUSLO ;?
03000 STXZ BUSHI
03100 JMP INTXIT
03200
03300 ;Add HALVE to CURPOS. Fix CURPOS+2.
03400
03600 HCINOP: ;?
03700 ;Ack host.
03800 JMP INTXIT
03900
04000 NMI ← START ;Reset??
04100 ;Interrupt vectors.
04200 LOC 177772
04300 NMI∧377
04400 (NMI⊗-10)∧377
04500 START∧377
04600 (START⊗-10)∧377
04700 TICK∧377
04800 (TICK⊗-10)∧377
04900 END